//
//  ThreadChapterViewController.m
//  ExerciseOC
//
//  Created by 王子曦 on 2025/4/14.
//

#import "ThreadChapterViewController.h"

@interface ThreadChapterViewController ()
@property (nonatomic, strong) NSThread *persistentThread;
@property (nonatomic, assign) BOOL shouldKeepRunning;
@end

@implementation ThreadChapterViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    [self setupUI];
}

- (void)setupUI {
    // 添加说明标签
    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, self.view.bounds.size.width - 40, 30)];
    titleLabel.text = @"GCD多线程示例（请查看控制台输出）：";
    [self.view addSubview:titleLabel];
    
    // 创建按钮 - 修改buttonTitles数组
    NSArray *buttonTitles = @[@"串行队列-同步执行", @"串行队列-异步执行", @"并发队列-同步执行", @"并发队列-异步执行", @"死锁案例", @"GCD实现多读单写", @"NSThread和RunLoop实现常驻线程"];
    NSArray *selectors = @[[NSValue valueWithPointer:@selector(demonstrateSerialSync)],
                          [NSValue valueWithPointer:@selector(demonstrateSerialAsync)],
                          [NSValue valueWithPointer:@selector(demonstrateConcurrentSync)],
                          [NSValue valueWithPointer:@selector(demonstrateConcurrentAsync)],
                          [NSValue valueWithPointer:@selector(demonstrateDeadlock)],
                          [NSValue valueWithPointer:@selector(demonstrateReadWriteLock)],
                          [NSValue valueWithPointer:@selector(demonstratePersistentThread)]];
    
    for (NSInteger i = 0; i < buttonTitles.count; i++) {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
        button.frame = CGRectMake(20, 140 + i * 50, self.view.bounds.size.width - 40, 40);
        [button setTitle:buttonTitles[i] forState:UIControlStateNormal];
        [button addTarget:self action:[selectors[i] pointerValue] forControlEvents:UIControlEventTouchUpInside];
        button.backgroundColor = [UIColor systemBlueColor];
        [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        button.layer.cornerRadius = 8;
        [self.view addSubview:button];
    }
}

// 串行队列-同步执行
- (void)demonstrateSerialSync {
    dispatch_queue_t serialQueue = dispatch_queue_create("com.example.serialQueue", DISPATCH_QUEUE_SERIAL);
    
    NSLog(@"\n=== 串行队列-同步执行 ===\n");
    NSLog(@"主线程开始: %@", [NSThread currentThread]);
    
    dispatch_sync(serialQueue, ^{
        NSLog(@"任务1: %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1];
    });
    
    dispatch_sync(serialQueue, ^{
        NSLog(@"任务2: %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1];
    });
    
    NSLog(@"主线程结束: %@\n", [NSThread currentThread]);
}

// 串行队列-异步执行
- (void)demonstrateSerialAsync {
    dispatch_queue_t serialQueue = dispatch_queue_create("com.example.serialQueue", DISPATCH_QUEUE_SERIAL);
    
    NSLog(@"\n=== 串行队列-异步执行 ===\n");
    NSLog(@"主线程开始: %@", [NSThread currentThread]);
    
    dispatch_async(serialQueue, ^{
        NSLog(@"任务1: %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1];
    });
    
    dispatch_async(serialQueue, ^{
        NSLog(@"任务2: %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1];
    });
    
    NSLog(@"主线程结束: %@\n", [NSThread currentThread]);
}

// 并发队列-同步执行
- (void)demonstrateConcurrentSync {
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    
    NSLog(@"\n=== 并发队列-同步执行 ===\n");
    NSLog(@"主线程开始: %@", [NSThread currentThread]);
    
    // dispatch_sync(concurrentQueue, ^{
    //     NSLog(@"任务1: %@", [NSThread currentThread]);
    //     [NSThread sleepForTimeInterval:1];
    // });
    
    // dispatch_sync(concurrentQueue, ^{
    //     NSLog(@"任务2: %@", [NSThread currentThread]);
    //     [NSThread sleepForTimeInterval:1];
    // });
    // 添加更多任务展示并发能力
    for (int i = 0; i < 5; i++) {
        dispatch_sync(concurrentQueue, ^{
            NSLog(@"任务%d: %@", i+1, [NSThread currentThread]);
            [NSThread sleepForTimeInterval:1];
        });
    }
    
    NSLog(@"主线程结束: %@\n", [NSThread currentThread]);
}

// 并发队列-异步执行
- (void)demonstrateConcurrentAsync {
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    
    NSLog(@"\n=== 并发队列-异步执行 ===\n");
    NSLog(@"主线程开始: %@", [NSThread currentThread]);
    
    dispatch_async(concurrentQueue, ^{
        NSLog(@"任务1: %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1];
    });
    
    dispatch_async(concurrentQueue, ^{
        NSLog(@"任务2: %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1];
    });
    
    NSLog(@"主线程结束: %@\n", [NSThread currentThread]);
}

// 新增死锁案例方法
- (void)demonstrateDeadlock {
    NSLog(@"\n=== 死锁案例 ===\n");
    NSLog(@"主线程开始: %@", [NSThread currentThread]);
    
    // 典型死锁案例1: 在主队列同步执行
//    dispatch_sync(dispatch_get_main_queue(), ^{
//        NSLog(@"这行代码永远不会执行");
//    });

        // 这个崩溃是由于在主线程上同步向主队列提交任务导致的死锁。让我详细解释一下原因和崩溃信息：

        // ## 崩溃原因分析
        // 1. 死锁形成机制 ：
        
        // - 主线程正在执行 demonstrateDeadlock 方法
        // - 当执行到 dispatch_sync(dispatch_get_main_queue(), ^{...}) 时：
        //     - dispatch_sync 会阻塞当前线程(主线程)直到block执行完成
        //     - 但block被提交到主队列，而主队列是串行队列
        //     - 主队列当前正在执行 demonstrateDeadlock 方法
        //     - 所以block必须等待 demonstrateDeadlock 执行完才能执行
        //     - 而 demonstrateDeadlock 又在等待block执行完
        //     - 形成互相等待的死锁

    
    // 典型死锁案例2: 串行队列嵌套同步执行
    
    dispatch_queue_t serialQueue = dispatch_queue_create("com.example.deadlockQueue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(serialQueue, ^{
        dispatch_sync(serialQueue, ^{
            NSLog(@"这行代码也永远不会执行");
        });
    });
    // # 串行队列嵌套同步执行导致的死锁详解
    // 这段代码展示了一个典型的GCD死锁案例，让我详细解释其死锁形成的原因和机制：

    // ## 代码分析
    // ```objective-c
    // dispatch_queue_t serialQueue = dispatch_queue_create("com.example.deadlockQueue", DISPATCH_QUEUE_SERIAL);
    // dispatch_async(serialQueue, ^{
    //     dispatch_sync(serialQueue, ^{
    //         NSLog(@"这行代码也永远不会执行");
    //     });
    // });
    // ```
    // ```

    // ## 死锁形成过程
    // 1. 队列创建 ：
    
    // - 创建了一个串行队列 serialQueue （ DISPATCH_QUEUE_SERIAL ）
    // - 串行队列的特性：任务按顺序执行，一次只执行一个任务
    // 2. 外层异步提交 ：
    
    // - dispatch_async 将第一个block异步提交到 serialQueue
    // - 异步提交不会阻塞当前线程
    // - 这个block成为队列的第一个任务
    // 3. 内层同步提交 ：
    
    // - 在第一个block内部，使用 dispatch_sync 同步提交第二个block到同一个串行队列
    // - 同步提交会阻塞当前线程，直到block执行完成
    // ## 死锁的具体原因
    // 1. 执行顺序冲突 ：
    
    // - 串行队列当前正在执行第一个block（外层block）
    // - 第一个block内部又同步提交第二个block到同一个队列
    // - 第二个block必须等待第一个block执行完成才能执行
    // - 但第一个block又在等待第二个block执行完成（因为 dispatch_sync 会阻塞）
    // - 形成互相等待的循环依赖
    // 2. GCD队列特性 ：
    
    // - 串行队列一次只能执行一个任务
    // - 同步提交( dispatch_sync )会阻塞当前线程直到任务完成
    // - 异步提交( dispatch_async )只是将任务放入队列，不阻塞当前线程
    // 3. 线程状态 ：
    
    // - 外层block在一个后台线程执行（由GCD分配的线程）
    // - 这个线程被内层的 dispatch_sync 阻塞
    // - 但内层block无法执行，因为队列被外层block占用
    // ## 可视化执行流程
    // ```plaintext
    // 时间线:
    // 1. serialQueue: [开始执行block1]
    // 2. block1内部: dispatch_sync(serialQueue, block2)
    // - block2被加入serialQueue队列末尾
    // - 当前线程(执行block1的线程)被阻塞，等待block2完成
    // 3. serialQueue状态:
    // - 当前任务: block1 (正在执行但被阻塞)
    // - 等待任务: block2
    // 4. block2无法开始执行，因为block1还未完成
    // 5. block1无法完成，因为它在等待block2完成
    // → 死锁形成
    // ```

    // ## 如何避免这种死锁
    // 1. 避免在串行队列中同步提交到同一队列
    // 2. 使用并发队列替代串行队列 （如果是这种嵌套模式）
    // 3. 将同步提交改为异步提交 （如果不关心执行顺序）
    // 4. 使用不同的队列 进行嵌套操作
    // ## 实际开发中的建议
    // 这种死锁模式在实际开发中常见于：

    // - 在自定义串行队列中进行同步回调
    // - 在数据处理流水线中不恰当地使用同步调用
    // - 在递归函数中使用同步提交到同一队列
    // 理解这种死锁机制对于编写健壮的并发代码非常重要，特别是在设计复杂任务链时。
    // 避免在串行队列中同步提交到同一队列是一种常见的优化策略，以避免不必要的等待和死锁。
    
    
    NSLog(@"主线程结束: %@\n", [NSThread currentThread]);
}

#pragma mark - 新增方法实现

// GCD实现多读单写
- (void)demonstrateReadWriteLock {
    NSLog(@"\n=== GCD实现多读单写 ===\n");
    
    // 1. 创建并发队列
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.readWriteQueue", DISPATCH_QUEUE_CONCURRENT);
    
    // 2. 模拟共享数据
    __block NSMutableDictionary *sharedData = [NSMutableDictionary dictionary];
    
    // 3. 写入操作
    for (int i = 0; i < 3; i++) {
        dispatch_barrier_async(concurrentQueue, ^{
            NSString *key = [NSString stringWithFormat:@"key%d", i];
            NSString *value = [NSString stringWithFormat:@"value%d", i];
            [sharedData setObject:value forKey:key];
            NSLog(@"写入数据: %@=%@ (线程: %@)", key, value, [NSThread currentThread]);
            [NSThread sleepForTimeInterval:0.5];
        });
    }
    
    // 4. 读取操作
    for (int i = 0; i < 5; i++) {
        dispatch_async(concurrentQueue, ^{
            NSString *key = [NSString stringWithFormat:@"key%d", arc4random_uniform(3)];
            NSString *value = [sharedData objectForKey:key];
            NSLog(@"读取数据: %@=%@ (线程: %@)", key, value, [NSThread currentThread]);
            [NSThread sleepForTimeInterval:0.3];
        });
    }
    
    // 5. 再次写入
    dispatch_barrier_async(concurrentQueue, ^{
        [sharedData setObject:@"finalValue" forKey:@"finalKey"];
        NSLog(@"最后写入: finalKey=finalValue (线程: %@)", [NSThread currentThread]);
    });
}

// NSThread和RunLoop实现常驻线程
- (void)demonstratePersistentThread {
    NSLog(@"\n=== NSThread和RunLoop实现常驻线程 ===\n");
    
    // 1. 创建常驻线程
    NSThread *persistentThread = [[NSThread alloc] initWithTarget:self selector:@selector(runPersistentThread) object:nil];
    [persistentThread start];
    
    // 2. 向常驻线程提交任务
    [self performSelector:@selector(task1) onThread:persistentThread withObject:nil waitUntilDone:NO];
    [self performSelector:@selector(task2) onThread:persistentThread withObject:nil waitUntilDone:NO];
    self.persistentThread = persistentThread;
}

// 常驻线程的典型应用场景及实现案例

//常驻线程特别适合需要长期运行、定时执行或需要保持线程状态的任务。以下是几个典型应用场景及实现代码：
// 1. 实时数据监控

// 在runPersistentThread方法中添加
- (void)runPersistentThread {
    @autoreleasepool {
        NSLog(@"常驻线程启动: %@", [NSThread currentThread]);
        
        // 创建数据监控定时器
        NSTimer *monitorTimer = [NSTimer timerWithTimeInterval:2.0
                                                       target:self
                                                     selector:@selector(monitorSystemStatus:)
                                                     userInfo:nil
                                                      repeats:YES];
        
        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addTimer:monitorTimer forMode:NSDefaultRunLoopMode];
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        // 使用可控的运行方式
        self.shouldKeepRunning = YES;
        while (self.shouldKeepRunning) {
            [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
        NSLog(@"常驻线程安全退出");
    }
}

// 添加停止方法
- (void)stopPersistentThread {
    if (self.persistentThread && self.persistentThread.isExecuting) {
        // 在常驻线程上设置停止标志
        [self performSelector:@selector(setShouldKeepRunning:)
                   onThread:self.persistentThread
                 withObject:@(NO)
              waitUntilDone:NO];
        
        // 唤醒RunLoop
        CFRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]);
        
        // 等待线程完成
        [self.persistentThread cancel];
    }
    self.persistentThread = nil;
}

// 在viewWillDisappear或dealloc中停止线程
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self stopPersistentThread];
}

- (void)dealloc {
    [self stopPersistentThread];
    NSLog(@"ViewController已释放");
}

- (void)monitorSystemStatus:(NSTimer *)timer {
    // 模拟获取系统状态数据
    CGFloat cpuUsage = (CGFloat)(arc4random_uniform(10000)) / 100.0;
    CGFloat memoryUsage = (CGFloat)(arc4random_uniform(10000)) / 100.0;
    
    NSLog(@"监控数据 - CPU: %.2f%%, 内存: %.2f%%", cpuUsage, memoryUsage);
    
    // 通知主线程更新UI
    dispatch_async(dispatch_get_main_queue(), ^{
        // 这里可以更新UI显示监控数据
    });
}

- (void)task1 {
    NSLog(@"执行任务1 (线程: %@)", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:1];
}

- (void)task2 {
    NSLog(@"执行任务2 (线程: %@)", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:1];
}

@end
